package me.zhouzhuo810.stringsmanager.action;

import com.google.common.collect.Lists;
import com.intellij.notification.*;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.vfs.VirtualFile;
import me.zhouzhuo810.stringsmanager.bean.StringEntity;
import me.zhouzhuo810.stringsmanager.utils.FileUtils;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;

public class CopyNonTranslateKeyAction extends AnAction {
    @Override
    public void actionPerformed(AnActionEvent e) {

        VirtualFile file = e.getData(PlatformDataKeys.VIRTUAL_FILE);
        if (file == null) {
            showError("找不到目标文件");
            return;
        }

        if (file.isDirectory()) {
            showError("请选择strings.xml或arrays.xml文件");
            return;
        } else if (!file.getName().endsWith(".xml")) {
            showError("请选择strings.xml或arrays.xml文件");
            return;
        } else if (!file.getName().contains("strings") && !file.getName().contains("arrays")) {
            showError("请选择strings.xml或arrays.xml文件");
            return;
        }

        if (file.getParent().getName().equalsIgnoreCase("values")) {
            showError("请选择其他语言的strings.xml或arrays.xml文件");
            return;
        }



        if (file.getName().contains("strings")) {
            //其他语言的Strings
            LinkedHashMap<String, String> keyValues = new LinkedHashMap<>();
            parseKeyValues(file, keyValues);
            //默认语言的Strings
            VirtualFile resDir = file.getParent().getParent();
            if (resDir.getName().equalsIgnoreCase("res")) {
                VirtualFile[] children = resDir.getChildren();
                for (VirtualFile child : children) {
                    if (child.getName().equals("values")) {
                        if (child.isDirectory()) {
                            VirtualFile[] values = child.getChildren();
                            for (VirtualFile value : values) {
                                if (value.getName().equals("strings.xml")) {
                                    LinkedHashMap<String, String> keyValuesDef = new LinkedHashMap<>();
                                    parseKeyValues(value, keyValuesDef);
                                    String content = getNonTranslationContent(keyValuesDef, keyValues);
                                    Toolkit.getDefaultToolkit()
                                            .getSystemClipboard()
                                            .setContents(new StringSelection(content), null);
                                    sendNotify("未翻译内容已复制到剪切板~");
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        } else {
            //其他语言的Strings
            LinkedHashMap<String, String> keyValues = new LinkedHashMap<>();
            parseKeyValuesArrays(file, keyValues);
            //默认语言的Strings
            VirtualFile resDir = file.getParent().getParent();
            if (resDir.getName().equalsIgnoreCase("res")) {
                VirtualFile[] children = resDir.getChildren();
                for (VirtualFile child : children) {
                    if (child.getName().equals("values")) {
                        if (child.isDirectory()) {
                            VirtualFile[] values = child.getChildren();
                            for (VirtualFile value : values) {
                                if (value.getName().equals("arrays.xml")) {
                                    LinkedHashMap<String, String> keyValuesDef = new LinkedHashMap<>();
                                    parseKeyValuesArrays(value, keyValuesDef);
                                    String content = getNonTranslationContentArrays(keyValuesDef, keyValues);
                                    Toolkit.getDefaultToolkit()
                                            .getSystemClipboard()
                                            .setContents(new StringSelection(content), null);
                                    sendNotify("未翻译内容已复制到剪切板~");
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }


    private String getNonTranslationContentArrays(LinkedHashMap<String, String> keyValuesDef, LinkedHashMap<String, String> keyValuesOther) {
        Set<String> keySetDef = keyValuesDef.keySet();
        Set<String> keySetOther = keyValuesOther.keySet();
        StringBuilder sb = new StringBuilder();
        for (String key : keySetDef) {
            if (!keySetOther.contains(key)) {
                String value = keyValuesDef.get(key);
                String[] split = value.split("\n");
                for (int i = 0; i < split.length; i++) {
                    String s = split[i];
                    sb.append(i == 0 ? key : "").append("\t").append(s).append("\n");
                }
            }
        }
        sb.append("\n");
        return sb.toString();
    }



    private void parseKeyValuesArrays(VirtualFile file, LinkedHashMap<String, String> keyValues) {
        List<StringEntity> strings;
        InputStream is = null;
        try {
            is = file.getInputStream();
            strings = extraStringEntityArrays(is);
            if (strings != null) {
                for (StringEntity string : strings) {
                    keyValues.put(string.getId(), string.getValue());
                }
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        } finally {
            FileUtils.closeQuietly(is);
        }

    }


    private List<StringEntity> extraStringEntityArrays(InputStream is) {
        List<StringEntity> strings = Lists.newArrayList();
        try {
            return generateStringsArrays(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is), strings);
        } catch (SAXException | IOException | ParserConfigurationException e) {
            throw new RuntimeException(e);
        }
    }

    private List<StringEntity> generateStringsArrays(Node node, List<StringEntity> strings) {
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            if (node.getNodeName().equals("string-array")) {
                String key = node.getAttributes().getNamedItem("name").getNodeValue();
                if (!(key.contains("_icon") || key.contains("_id") || key.contains("_version") || key.contains("_codes"))) {
                    NodeList childNodes = node.getChildNodes();
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < childNodes.getLength(); i++) {
                        Node item = childNodes.item(i);
                        if (item.getNodeName().equals("item")) {
                            sb.append(item.getTextContent()).append("\n");
                        }
                    }
                    sb.deleteCharAt(sb.length() - 1);
                    strings.add(new StringEntity(key, sb.toString(), true));
                }
            } else {
                NodeList children = node.getChildNodes();
                for (int j = 0; j < children.getLength(); j++) {
                    generateStringsArrays(children.item(j), strings);
                }
            }
        } else {
            NodeList children = node.getChildNodes();
            for (int j = 0; j < children.getLength(); j++) {
                generateStringsArrays(children.item(j), strings);
            }
        }
        return strings;
    }


    private void sendNotify(String content) {
        NotificationGroup notificationGroup = new NotificationGroup("copy_non_translation_id", NotificationDisplayType.BALLOON, false);
        Notification notification = notificationGroup.createNotification(content, MessageType.INFO);
        Notifications.Bus.notify(notification);
    }

    private String getNonTranslationContent(LinkedHashMap<String, String> keyValuesDef, LinkedHashMap<String, String> keyValuesOther) {
        Set<String> keySetDef = keyValuesDef.keySet();
        Set<String> keySetOther = keyValuesOther.keySet();
        StringBuilder sb = new StringBuilder();
        for (String key : keySetDef) {
            if (!keySetOther.contains(key)) {
                sb.append(key).append("\n");
            }
        }
        return sb.toString();
    }


    private void parseKeyValues(VirtualFile file, LinkedHashMap<String, String> keyValues) {
        List<StringEntity> strings;
        InputStream is = null;
        try {
            is = file.getInputStream();
            strings = extraStringEntity(is);
            if (strings != null) {
                for (StringEntity string : strings) {
                    keyValues.put(string.getId(), string.getValue());
                }
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        } finally {
            FileUtils.closeQuietly(is);
        }

    }

    private List<StringEntity> extraStringEntity(InputStream is) {
        List<StringEntity> strings = Lists.newArrayList();
        try {
            return generateStrings(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is), strings);
        } catch (SAXException | IOException | ParserConfigurationException e) {
            throw new RuntimeException(e);
        }
    }

    private List<StringEntity> generateStrings(Node node, List<StringEntity> strings) {
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            if (node.getNodeName().equals("string")) {
                String key = node.getAttributes().getNamedItem("name").getNodeValue();
                String value = node.getTextContent();
                strings.add(new StringEntity(key, value, false));
            } else {
                NodeList children = node.getChildNodes();
                for (int j = 0; j < children.getLength(); j++) {
                    generateStrings(children.item(j), strings);
                }
            }
        } else {
            NodeList children = node.getChildNodes();
            for (int j = 0; j < children.getLength(); j++) {
                generateStrings(children.item(j), strings);
            }
        }
        return strings;
    }


    private void showError(String msg) {
        Notifications.Bus.notify(new Notification("StringManager", "StringManager", msg, NotificationType.ERROR));
    }
}
